﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Data;

namespace NovoDataBase
{
    [Serializable]
    public class BitField
    {
        uint mask;
        Register ReportedReg;

        public BitField(Register _reg, RegRow _regRow)
        {
            this.ReportedReg = _reg;
            this.bfName = _regRow.bfName;
            this.startBit = _regRow.bfStartBit;
            this.endBit = _regRow.bfEndBit;
            this.bitWidth = this.endBit - this.startBit + 1;
            this.mask = maskGen(startBit, (int)bitWidth);
            this.bfValue = _regRow.defaultValue;
            this.rwPro = _regRow.access;
            this.bfPermission = _regRow.attribute;
            this.bfDesc = _regRow.bfDescription;
        }

        /// <summary>
        /// Initialize bit field and set default bit field value.
        /// </summary>
        /// <param name="bits">Contain bits start and end infomation</param>
        /// <param name="name">the name of this bit field</param>
        /// <param name="description">bit field description, include each bit value description</param>
        /// <param name="value">default register value</param>
        public BitField(Register _Reg, string _bits, int byteCountOfReg, string name, string description, string regValue)
        {

            ////Get the reg handler of this bitfield belongs to
            //ReportedReg = _Reg;

            //// Set name firstly is good for init when register init. Can update bf later.
            //bfName = name;
            //    return;

            //// Get byte count of this bf
            //string[] bits_inByte = _bits.Trim().Replace("\r\n", ",").Split(',');
            //if(bits_inByte == null || bits_inByte.Length == 0)
            //    return;


            //// calc end bit and start bit index
            //string[] bits_ix;
            //int bracketIx1, bracketIx2;
            //byteCountOfReg = (byteCountOfReg > 4) ? 4 : byteCountOfReg;         // if byteCountOfReg > 4, will just use 4 instead
            //if (byteCount == 1)     // this bf length is less than 8bits
            //{
            //    // Normal registger, each reg contains 8 bits value, bits should like [x:y] or [x]
            //    if (bits_inByte.Length <= 5)
            //    {
            //        bits_ix = bits_inByte[0].Trim("[]".ToCharArray()).Split(':');
            //        int.TryParse(bits_ix[0], out endBit);
            //        int.TryParse(bits_ix[bits_ix.Length - 1], out startBit);    // if length is 1([x]), then startbit = endBit;if 2([x:y]), then they are different
            //    }
            //    // 1 reg contains more than 1 bytes, bits should like bytex[y:z] or bytex[y]
            //    else
            //    {
            //        bracketIx1 = bits_inByte[0].IndexOf("[");
            //        bracketIx2 = bits_inByte[0].IndexOf("]");
            //        int _byteIx = int.Parse(bits_inByte[0].Substring(bracketIx1 - 1, 1));

            //        bits_ix = bits_inByte[0].Substring(bracketIx1, bracketIx2 - bracketIx1 + 1).Trim("[]".ToCharArray()).Split(':');
            //        int.TryParse(bits_ix[0], out endBit);
            //        int.TryParse(bits_ix[bits_ix.Length - 1], out startBit);
            //        endBit += (byteCountOfReg - _byteIx - 1) * 8;
            //        startBit += (byteCountOfReg - _byteIx - 1) * 8;
            //    }
            //}
            //else  // some case like bytex1[y1:z1], bytex2[y2:z2]...
            //{
            //    // Calc end bit
            //    bracketIx1 = bits_inByte[0].IndexOf("[");
            //    bracketIx2 = bits_inByte[0].IndexOf("]");
            //    int _byteIx = int.Parse(bits_inByte[0].Substring(bracketIx1 - 1, 1));

            //    bits_ix = bits_inByte[0].Substring(bracketIx1, bracketIx2 - bracketIx1 + 1).Trim("[]".ToCharArray()).Split(':');
            //    int.TryParse(bits_ix[0], out endBit);
            //    endBit += (byteCountOfReg - _byteIx - 1) * 8;

            //    // Calc start bit
            //    bracketIx1 = bits_inByte[bits_inByte.Length - 1].IndexOf("[");
            //    bracketIx2 = bits_inByte[bits_inByte.Length - 1].IndexOf("]");
            //    _byteIx = int.Parse(bits_inByte[bits_inByte.Length - 1].Substring(bracketIx1 - 1, 1));

            //    bits_ix = bits_inByte[bits_inByte.Length - 1].Substring(bracketIx1, bracketIx2 - bracketIx1 + 1).Trim("[]".ToCharArray()).Split(':');
            //    int.TryParse(bits_ix[bits_ix.Length - 1], out startBit);
            //    startBit += (byteCountOfReg - _byteIx - 1) * 8;
            //}

            //// Calc bitWidth            
            //bitWidth = endBit - startBit + 1;

            //// Get bf description
            //bfDesc = description;

            //// calc mask based on startBit and bitWidth
            //mask = maskGen(startBit, bitWidth);

            //uint.TryParse(regValue.Replace("0x",""), System.Globalization.NumberStyles.HexNumber, null, out bfValue);
            //bfValue = (bfValue & mask) >> startBit;

            ////bitValueMeaning = new string[(int)Math.Pow(2, bitWidth)];
            ////Console.WriteLine(BFValueInRegValue.ToString("X2"));        
        }

        public void InitiBF(Register _Reg, string _bits, int byteCountOfReg, string name, string description, string regValue)
        {
            //    //Get the reg handler of this bitfield belongs to
            //    ReportedReg = _Reg;

            //    // Set name firstly is good for init when register init. Can update bf later.
            //    bfName = name;

            //    // if no bits info inputed
            //    bits = _bits.Replace("\n","").Replace(",", "\r\n"); ; //_bits.Replace("[","").Replace("]","");
            //    if (bits == null || bits.Length == 0 || name == "")
            //        return;

            //    // Get byte count of this bf
            //    string[] bits_inByte = _bits.Trim().Replace("\n", "").Replace(" ", "").Replace("\r\n", ",").Split(',');
            //    if(bits_inByte == null || bits_inByte.Length == 0)
            //        return;

            //    byteCount = bits_inByte.Length;
            //    bfValue_byte = new byte[byteCount];

            //    // calc end bit and start bit index
            //    string[] bits_ix;
            //    int bracketIx1, bracketIx2;
            //    byteCountOfReg = (byteCountOfReg > 4) ? 4 : byteCountOfReg;         // if byteCountOfReg > 4, will just use 4 instead
            //    if (byteCount == 1)     // this bf length is less than 8bits
            //    {
            //        // Normal registger, each reg contains 8 bits value, bits should like [x:y] sor [x]
            //        if (bits_inByte[0].Length <= 5)
            //        {
            //            bits_ix = bits_inByte[0].Trim("[]".ToCharArray()).Split(':');
            //            int.TryParse(bits_ix[0], out endBit);
            //            int.TryParse(bits_ix[bits_ix.Length - 1], out startBit);    // if length is 1([x]), then startbit = endBit;if 2([x:y]), then they are different
            //        }
            //        // 1 reg contains more than 1 bytes, bits should like bytex[y:z] or bytex[y]
            //        else
            //        {
            //            bracketIx1 = bits_inByte[0].IndexOf("[");
            //            bracketIx2 = bits_inByte[0].IndexOf("]");
            //            int _byteIx = int.Parse(bits_inByte[0].Substring(bracketIx1 - 1, 1));

            //            bits_ix = bits_inByte[0].Substring(bracketIx1, bracketIx2 - bracketIx1 + 1).Trim("[]".ToCharArray()).Split(':');
            //            int.TryParse(bits_ix[0], out endBit);
            //            int.TryParse(bits_ix[bits_ix.Length - 1], out startBit);
            //            endBit += (byteCountOfReg - _byteIx - 1) * 8;
            //            startBit += (byteCountOfReg - _byteIx - 1) * 8;
            //        }
            //    }
            //    else  // some case like bytex1[y1:z1], bytex2[y2:z2]...
            //    {
            //        // Calc end bit
            //        bracketIx1 = bits_inByte[0].IndexOf("[");
            //        bracketIx2 = bits_inByte[0].IndexOf("]");
            //        //int _byteIx = int.Parse(bits_inByte[0].Substring(bracketIx1 - 1, 1));

            //        bits_ix = bits_inByte[0].Substring(bracketIx1, bracketIx2 - bracketIx1 + 1).Trim("[]".ToCharArray()).Split(':');
            //        int.TryParse(bits_ix[0], out endBit);
            //        //endBit += (byteCountOfReg - _byteIx - 1) * 8;
            //        endBit += (byteCountOfReg - 1) * 8;

            //        // Calc start bit
            //        bracketIx1 = bits_inByte[bits_inByte.Length - 1].IndexOf("[");
            //        bracketIx2 = bits_inByte[bits_inByte.Length - 1].IndexOf("]");
            //        //_byteIx = int.Parse(bits_inByte[bits_inByte.Length - 1].Substring(bracketIx1 - 1, 1));

            //        bits_ix = bits_inByte[bits_inByte.Length - 1].Substring(bracketIx1, bracketIx2 - bracketIx1 + 1).Trim("[]".ToCharArray()).Split(':');
            //        int.TryParse(bits_ix[bits_ix.Length - 1], out startBit);
            //        //startBit += (byteCountOfReg - _byteIx - 1) * 8;
            //    }

            //    // Calc bitWidth            
            //    bitWidth = endBit - startBit + 1;

            //    // Get bf description
            //    bfDesc = description;

            //    // calc mask based on startBit and bitWidth
            //    mask = maskGen(startBit, bitWidth);

            //    uint.TryParse(regValue.Replace("0x",""), System.Globalization.NumberStyles.HexNumber, null, out bfValue);
            //    bfValue = (bfValue & mask) >> startBit;

            //    //bitValueMeaning = new string[(int)Math.Pow(2, bitWidth)];
            //    //Console.WriteLine(BFValueInRegValue.ToString("X2"));
        }

        private uint maskGen(uint _startIx, int _len)
        {
            uint mask = ((uint)Math.Pow(2, _len) - 1) << (int)_startIx;
            return mask;
        }

        public uint BFMask
        {
            get { return this.mask; }
        }

        private string bits;
        public string BITs
        {
            get 
            { 
                return (startBit == endBit) ? 
                    string.Format("[{0}]", startBit) : 
                    string.Format("[{0}:{1}]", startBit, endBit); 
            }
        }

        private uint startBit;
        public uint StartBit
        {
            get { return startBit; }
        }

        private uint endBit;
        public uint EndBit
        {
            get { return endBit; }
        }

        private uint bitWidth;
        public uint BitWidth
        {
            get { return bitWidth; }
        }

        private int byteCount = 1;
        public int ByteCount
        {
            get { return this.byteCount; }
        }

        private RWProperty rwPro;
        public RWProperty RWPro
        {
            get { return rwPro; }
        }

        private Permission bfPermission = Permission.Public;
        public Permission BFPermission
        { get { return bfPermission; } }

        // This value just should in bf value on GUI, not the value in register
        private uint bfValue;
        public uint BFValue
        { 
            get { return bfValue; }
            // Due to set the bif field value with reg value, mask is needed
            set 
            { 
                bfValue = value;

                // Update reg value
                uint temp = ReportedReg.RegValue;

                temp &= ~mask;
                temp |= BFValueInRegValue;

                ReportedReg.RegValue = temp;
            } 
        }

        public string BFValueString
        {
            get
            {
                if (byteCount <= 4)
                    return bfValue.ToString(String.Format("X{0}", byteCount * 2));
                else
                    return "";
            }
        }

        private byte[] bfValue_byte;
        public byte[] BFValue_byte
        {
            get 
            {
                uint tempValue = bfValue;
                uint byteMask = 0xFF;
                for (int ix = 0; ix < byteCount; ix++)
                {
                    bfValue_byte[byteCount - ix - 1] = (byte)((tempValue >> (ix * 8)) & byteMask);
                }

                return this.bfValue_byte; 
            }
            set
            {
                for (int ix = 0; ix < byteCount; ix++)
                    bfValue_byte[ix] = value[ix];
            }
        }

        public uint BFMaxValue
        {
            get { return (uint)Math.Pow(2, bitWidth) - 1; }
        }

        // This is the value in the register, which means added offset in bfValue
        public uint BFValueInRegValue
        {
            get { return bfValue << (int)startBit; }
            set { bfValue = (value & mask) >> (int)startBit; } 
        }

        private string bfName;
        public string BFName
        {
            get { return bfName; }
        }

        private string bfDesc;
        public string BFDesc
        {
            get { return bfDesc; }
        }

        //private string[] bitValueMeaning;
        //public string[] BitValueMeaning
        //{
        //    get { return bitValueMeaning; }
        //}
    }

    [Serializable]
    public class Register
    {
        public Register(RegGroup _group, RegRow _regRow)
        {
            this.group = _group;
            this.regName = _regRow.regName;
            this.regDescription = _regRow.regDescription;
            if(_regRow.regOffset > _group.Size)  // the register already contain base. e.g.: 6D MIPI registers
                this.regAddr =_regRow.regOffset;
            else
                this.regAddr = _group.StartAddr + _regRow.regOffset;
            this.rwPro = _regRow.access;
            this.regPermission = _regRow.attribute;            

            bfList.Clear();            
        }

        /// <summary>
        /// One Register(8 bits)
        /// </summary>
        /// <param name="_regGroup">the group name.</param>
        /// <param name="_regName">Register name.</param>
        /// <param name="_regAddress">Register address.</param>
        /// <param name="_rw"> register access propery.</param>
        /// <param name="_defaultValue">Defalut Value. </param>
        /// <param name="_paras">Bit field names array, LSB first.
        /// 3 bf example:bit7 - bit0: bf_2, bf_1, bf_0 -> _paras[0] = bf_0.name ... _paras[2] = bf_2.name</param>
        public Register(string _regGroup, string _regName, string _regAddress, RWProperty _rw, string _defaultValue, params object[] _paras)
        {
            this.groupName = _regGroup;
            this.regName = _regName;
            this.regAddr = byte.Parse(_regAddress.Replace("0x",""), System.Globalization.NumberStyles.HexNumber);
            this.rwPro = _rw;
            this.regValue = byte.Parse(_defaultValue.Replace("0x", ""), System.Globalization.NumberStyles.HexNumber);
            this.paras = _paras;

            bfList.Clear();
            for(int ix = 0; ix < _paras.Length; ix++)
            {
                bfList.Add(new BitField(this, "", this.byteCount, (string)_paras[ix], "", ""));
            }
        }

        /// <summary>
        /// One Register, more than 8bits.
        /// </summary>
        /// <param name="_regGroup">the group name.</param>
        /// <param name="_regName">Register name.</param>
        /// <param name="_regAddress">Register address.</param>
        /// <param name="_rw"> register access propery.</param>
        /// <param name="_byteCount">how many bytes will belong this register.</param>
        /// <param name="_defaultValue">Defalut Value. </param>
        /// <param name="_paras">Bit field names array, LSB first.
        /// 3 bf example:bit7 - bit0: bf_2, bf_1, bf_0 -> _paras[0] = bf_0.name ... _paras[2] = bf_2.name</param>
        public Register(string _regGroup, string _regName, string _regAddress, RWProperty _rw, string _byteCount, string _defaultValue, params object[] _paras)
        {
            this.groupName = _regGroup;
            this.regName = _regName;
            this.regAddr = byte.Parse(_regAddress.Replace("0x", ""), System.Globalization.NumberStyles.HexNumber);
            this.rwPro = _rw;
            int.TryParse(_byteCount, out this.byteCount);
            regValue_byte = new byte[byteCount];

            this.regValue = 0 ;
            UInt32.TryParse(_defaultValue.Replace("0x", ""), System.Globalization.NumberStyles.HexNumber, null, out regValue);
            this.paras = _paras;

            bfList.Clear();
            for (int ix = 0; ix < _paras.Length; ix++)
            {
                bfList.Add(new BitField(this, "", this.byteCount, (string)_paras[ix], "", ""));
            }
        }

        private List<BitField> bfList = new List<BitField> { };

        private int byteCount = 4;
        public int ByteCount
        {
            get { return this.byteCount; }
        }

        private RegGroup group = null;
        public RegGroup Group
        { get { return group; } }   

        private string groupName;
        public string GroupName
        {
            set { this.groupName = value; }
            get { return groupName; }
        }

        private string regName;
        public string RegName
        {
            get { return regName; }
        }

        private string regDescription;
        public string RegDescription
        { get { return regDescription; } }  

        private UInt32 regAddr;
        //private UInt16 regAddr_u16;
        public UInt32 RegAddress
        {
            get { return regAddr; }
        }

        private RWProperty rwPro;
        public RWProperty RWPro
        {
            get { return rwPro; }
        }

        private Permission regPermission = Permission.Public;
        public Permission RegPermission
        { get { return regPermission; } }   

        private object[] paras;

        public bool UseByteArray
        {
            get { return byteCount > 1 ? true : false; }
        }

        public bool DisplayRegValueCell
        {
            get { return byteCount > 4 ? true : false; }
        }

        private UInt32 regValue = 0;
        public UInt32 RegValue
        {
            get { return regValue; }
            set
            {
                if (this.regValue != value && byteCount <= 4)
                {
                    this.regValue = value;
                    UpdateBFValue();
                }
            }
        }

        public String RegValueString
        {
            get 
            {
                if (byteCount <= 4)
                    return regValue.ToString(String.Format("X{0}", byteCount * 2));
                else
                    return "";
            }
        }

        // save register value as byte array, MSB first(e.g. bit24-31 save in regValue_byte[0])
        private byte[] regValue_byte = new byte[4];
        public byte[] ByteValue
        {
            get 
            {
                uint byteMask = 0xFF;
                if (byteCount <= 4)
                {
                    for (int ix = 0; ix < byteCount; ix++)
                    {
                        regValue_byte[byteCount - ix - 1] = (byte)((regValue >> (ix * 8)) & byteMask);
                    }
                }
                else
                {
                    int ix_dest = 0;
                    for (int ix_bf = 0; ix_bf < BFCount; ix_bf++)
                    {
                        Array.Copy(bfList[ix_bf].BFValue_byte, 0, regValue_byte, ix_dest, bfList[ix_bf].ByteCount);
                        ix_dest += bfList[ix_bf].ByteCount;
                        //for (int ix = 0; ix < bfList[ix_bf].ByteCount; ix++)
                        //{
                        //    regValue_byte[ix_dest++] = bfList[ix_bf].BFValue_byte[ix];
                        //}
                    }
                }
                return regValue_byte; 
            }
            set
            {
                for (int ix = 0; ix < byteCount; ix++)
                {
                    regValue_byte[ix] = value[ix];
                }
                if (byteCount <= 4)
                {
                    regValue = 0;
                    for (int ix = 0; ix < byteCount; ix++)
                    {
                        regValue <<= 8;
                        RegValue += regValue_byte[ix];
                    }
                }
                else
                {
                    int ix_dest = 0;
                    byte[] tempData = new byte[byteCount];
                    for (int ix_bf = 0; ix_bf < BFCount; ix_bf++)
                    {
                        Array.Copy(regValue_byte, ix_dest, tempData, 0, bfList[ix_bf].ByteCount);
                        ix_dest += bfList[ix_bf].ByteCount;
                        bfList[ix_bf].BFValue_byte = tempData;
                        //for (int ix = 0; ix < bfList[ix_bf].ByteCount; ix++)
                        //{
                            
                            //bfList[ix_bf].BFValue_byte[ix] = regValue_byte[ix_dest++];
                        //}
                    }
                }
            }
        }

        public int BFCount
        {
            get { return this.bfList.Count; }
        }

        public uint RegMaxValue
        {
            get 
            {
                if (byteCount == 1)
                    return byte.MaxValue;
                else if (byteCount == 2)
                    return UInt16.MaxValue;
                else if (byteCount == 4)
                    return UInt32.MaxValue;
                else
                    return 0;
            }
        }

        public bool AddBitField(BitField _bf)
        {
            if(this.bfList.Contains(_bf))
                return false;   

            this.bfList.Add(_bf); 
            return true;  
        }

        public bool AddBitField(RegRow _regRow)
        {
            foreach (BitField _bf in this.bfList)
            {
                if(_bf.BFName.ToUpper() == _regRow.bfName.ToUpper())
                    return false;
            }

            BitField newBF = new BitField(this, _regRow);
            this.bfList.Add(newBF);

            return true;
        }
        public BitField this[string name]
        {
            get
            {
                if(bfList.Count > 0)
                {
                    foreach (BitField bf in bfList)
                    {
                        if (bf.BFName.ToLower() == name.ToLower())
                            return bf;
                    }
                }
                return null;
            }
        }

        public BitField this[int ix]
        {
            get
            {
                if (bfList.Count > ix)
                {
                    return bfList[ix];
                }
                return null;
            }
        } 

        #region Methods
        public UInt32 GetBFValue(string _bfName)
        {
           return this[_bfName].BFValue;
        }

        public UInt32 GetBFValue(int _bfIx)
       {
           return bfList[_bfIx].BFValue;
       }
                
        private void UpdateBFValue()
        {
            // Can just update bf value with reg value, will mask inside BitField property
            foreach (BitField bf in bfList)
            {
                bf.BFValueInRegValue = this.regValue;
            }
        }

        private void UpdataRegValue()
        {
            UInt32 temp = 0;
            for (int ix = 0; ix < bfList.Count; ix++)
            {
                temp += bfList[ix].BFValueInRegValue;
            }
            this.regValue = temp;
        }

        public void SetBFValue(string _bfName, string _bfValue)
        {
            uint temp = regValue;
            BitField tempBF = this[_bfName];
            //tempBF.BFValue = _bfValue;
            tempBF.BFValue = uint.Parse(_bfValue, System.Globalization.NumberStyles.HexNumber);

            if (byteCount <= 4)
            {
                temp &= ~tempBF.BFMask;
                temp |= tempBF.BFValueInRegValue;

                this.regValue = temp;
            }
            else
            {
                // do nothing, because all data will store in byte array
            }
        }

        public bool Contain(string _bfName)
        {
            bool ret = false;
            foreach (BitField bf in bfList)
            {
                if (bf.BFName.ToUpper() == _bfName.ToUpper())
                    return true;
            }
            return ret;
        }

        #endregion Methods
    }

    [Serializable]
    public class RegGroup
    {
        List<Register> regList = new List<Register>();
        /// <summary>
        /// This is for excel importing, which is the original register groups
        /// </summary>
        /// <param name="_startAddr"></param>
        /// <param name="_endAddr"></param>
        /// <param name="_name"></param>
        /// <param name="_size"></param>
        /// <param name="_description"></param>
        /// <param name="_comment"></param>
        public RegGroup(UInt32 _startAddr, UInt32 _endAddr, string _name, UInt32 _size, string _description, string _comment)
        {
            this.startAddr = _startAddr;
            this.endAddr = _endAddr;
            this.name = _name;
            this.size = _size;
            this.description = _description;
            this.comment = _comment;
            this.groupType = 0;
        }

        /// <summary>
        /// This func is used for user define, no address range
        /// </summary>
        /// <param name="_name"></param>
        /// <param name="_description"></param>
        public RegGroup(string _name, string _description)
        {            
            this.name = _name;
            this.description = _description;
            this.groupType = 1;
        }

        private int groupType = 0;
        /// <summary>
        /// 0 - Default; 1- user defined
        /// </summary>
        public int GetGroupType
        {
            get { return this.groupType; }
        }

        private UInt32 startAddr = 0;
        public UInt32 StartAddr
        { get { return startAddr; } }

        private UInt32 endAddr = UInt32.MaxValue;
        public UInt32 EndAddr
        { get { return endAddr; } }

        private string name = string.Empty;
        public string Name
        { get { return name; } }

        private UInt32 size = 0;
        public UInt32 Size
        { get { return size; } }

        private string description = string.Empty;
        public string Description
        { get { return description; } }

        private string comment = string.Empty;
        public string Comment
        { get { return comment; } }

        public void Add(Register _reg)
        {
            this.regList.Add(_reg);
        }

        public void Remove(Register _reg)
        {
            this.regList.Remove(_reg);
        }

        public void RemoveAt(int index)
        {
            this.regList.RemoveAt(index);
        }

        public void Clear()
        {
            this.regList.Clear();
        }

        public int Count
        {
            get { return this.regList.Count; }
        }

        public bool Contain(string _regName)
        {
            foreach (Register reg in regList)
            {
                if (reg.RegName.ToLower() == _regName.ToLower())
                    return true;
            }

            return false;
        }

        public bool Contain(byte _regAddress)
        {
            if((_regAddress > endAddr) || (_regAddress < startAddr))
                return false;

            foreach (Register reg in regList)
            {
                if (reg.RegAddress == _regAddress)
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Get the register by register's address.
        /// </summary>
        /// <param name="_regAddress">Int type register address.</param>
        /// <returns></returns>
        public Register this[byte _regAddress]
        {
            get
            {
                foreach (Register reg in regList)
                {
                    if (reg.RegAddress == _regAddress)
                        return reg;
                }
                return null;
            }
        }

        /// <summary>
        /// Get the register by register's name.
        /// </summary>
        /// <param name="_regName">string type register name.</param>
        /// <returns></returns>
        public Register this[string _regName]
        {
            get
            {
                foreach (Register reg in regList)
                {
                    if (reg.RegName.ToLower() == _regName.ToLower())
                        return reg;
                }
                return null;
            }
        }

        public List<Register> RegList
        {
            get { return this.regList; }
        }
    }

    [Serializable]
    public class RegisterMap
    {
        //private uint devAddress = 0;
        //private List<Register> RegistersList = new List<Register> { };
        private List<RegGroup> RegGroupList = new List<RegGroup> { };
        public RegisterMap()
        {
            RegGroupList.Clear();
            //RegistersList.Clear();
        }

        //public uint DevAddr
        //{
        //    set { this.devAddress = value; }
        //    get { return this.devAddress; }
        //}
        //public bool InitRegMap(DataSet _ds)
        //{ }

        //public bool InitRegGroup(DataTable _dt)
        //{
        //    List<RegGroup> tempList = ExcelToRegMap.InitRegGroup(_dt);
        //    if (tempList != null)
        //    {
        //        this.RegGroupList = tempList;
        //        return true;
        //    }
        //    else
        //        return false;
        //}

        /// <summary>
        /// Default regGroup, which is decoded from original excel.
        /// </summary>
        /// <param name="regGroup"></param>
        /// <returns></returns>
        public bool AddGroup(RegGroup regGroup)
        {
            foreach (RegGroup _rg in RegGroupList)
            {
                if (_rg.Name == regGroup.Name)
                    return false;
            }

            RegGroupList.Add(regGroup);

            return true;
        }

        /// <summary>
        /// User defined group, which has UD_ prefix. And this group
        /// </summary>
        /// <param name="_groupName"></param>
        /// <returns></returns>
        public bool AddGroup(string _groupName)
        {
            string udGroupName = "UD_" + _groupName;
            foreach (RegGroup _rg in RegGroupList)
            {
                if (_rg.Name == udGroupName)
                    return false;
            }

            RegGroupList.Add(new RegGroup(udGroupName, "User Defined Group"));

            return true;
        }

        public int GroupCount
        {
            get { return this.RegGroupList.Count; }
        }

        public string GetGroupName(int _ix)
        {
            return this.RegGroupList[_ix].Name;
        }

        public RegGroup GetRegGroup(int _ix)
        {
            return this.RegGroupList[_ix];
        }

        //public void AddRegister(RegGroup _rg, Register _reg)
        //{
        //    _rg.Add(_reg);
        //}

        //public void RemoveRegister(Register _reg)
        //{
        //    this.RegistersList.Remove(_reg);
        //}

        //public void RemoveAt(int index)
        //{
        //    this.RegistersList.RemoveAt(index);
        //}

        //public void ClearAll()
        //{
        //    this.RegistersList.Clear();
        //}

        public int RegCount()
        {
            int regCnt = 0;

            foreach(RegGroup rg in this.RegGroupList)
            {
                regCnt = regCnt +  rg.Count;
            }

            return regCnt;
        }

        public bool Contain(string _regName)
        {
            foreach (RegGroup rg in RegGroupList)
            {
                if (rg.Contain(_regName))
                {
                    return true;
                }                
            }

            return false;
        }

        public bool Contain(byte _regAddress)
        {
            foreach (RegGroup rg in RegGroupList)
            {
                if (rg.Contain(_regAddress))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Get the register by register's address.
        /// </summary>
        /// <param name="_regAddress">Int type register address.</param>
        /// <returns></returns>
        public Register this[byte _regAddress]
        {
            get
            {
                foreach (RegGroup rg in RegGroupList)
                {
                    foreach (Register reg in rg.RegList)
                    {
                        if (reg.RegAddress == _regAddress)
                            return reg;
                    }
                }
                return null;
            }
        }
        public Register this[UInt32 _regAddress]
        {
            get
            {
                foreach (RegGroup rg in RegGroupList)
                {
                    foreach (Register reg in rg.RegList)
                    {
                        if (reg.RegAddress == _regAddress)
                            return reg;
                    }
                }
                return null;
            }
        }


        /// <summary>
        /// Get the register by register's name.
        /// </summary>
        /// <param name="_regName">string type register name.</param>
        /// <returns></returns>
        public Register this[string _regName]
        {
            get
            {
                foreach (RegGroup rg in RegGroupList)
                {
                    foreach (Register reg in rg.RegList)
                    {
                        if (reg.RegName.ToLower() == _regName.ToLower())
                            return reg;
                    }
                }
                return null;
            }
        }

        public List<Register> RegList
        {
            get 
            { 
                List<Register> tempList = new List<Register>();
                foreach (RegGroup rg in RegGroupList)
                    tempList.AddRange(rg.RegList);

                return tempList;
            }
        }
    }

    public enum IICMode
    {
        None = 0,
        A8D8 = 0x11,
        A8D16 = 0x12,
        A8D32 = 0x14,
        A16D8 = 0x21,
        A16D16 = 0x22,
        A16D32 = 0x24,
        A32D8 = 0x41,
        A32D16 = 0x42,
        A32D32 = 0x44
    }

}


